package org.app.appjson.adapter;

import org.app.appjson.writer.WriteHandler;
import org.app.appjson.exception.AppJsonException;
import org.app.appjson.reader.JsonLexer;
import org.app.appjson.reader.JsonToken;
import org.app.appjson.reader.ReadHandler;

import java.util.*;

/**
 * Map类型适配器
 * @author lizhongsi
 * @version 1.0
 * @since 1.0
 */
public class MapAdapter<K, V> implements TypeAdapter {

    public static <K, V> Map<K, V> read(ReadHandler handler) throws AppJsonException {
        JsonLexer lexer = handler.getLexer();
        if (lexer.peek().getType() == JsonToken.NULL) {
            lexer.next();
            return null;
        }
        if (lexer.peek().getType() == JsonToken.BEGIN_OBJECT) {
            lexer.next();// 消费 {
            Map<K, V> map = handler.newInstance();
            while (lexer.peek().getType() != JsonToken.END_OBJECT) {
                if (lexer.peek().getType() != JsonToken.STRING) {
                    throw new AppJsonException("The type of key must be String.");
                }
                K key = (K) lexer.next().getValue();// json的key必须是String
                // key之后必须是:
                if (lexer.peek().getType() != JsonToken.SEP_COLON) {
                    throw new AppJsonException("Except a char ':'.");
                }
                lexer.next();// 消费 :
                V value = handler.doRead();
                V replaced = map.put(key, value);
                if (replaced != null){
                    throw new AppJsonException("duplicate key: " + key);
                }
                // 消费两个键值对之间的 ,
                if (lexer.peek().getType() == JsonToken.SEP_COMMA) {
                    lexer.next();
                }
            }
            return map;
        }
        throw new AppJsonException("MapAdapter can not parse json stream.");
    }

    public static void write(WriteHandler handler) throws AppJsonException {
        Object object = handler.getObject();
        if (object == null) {
            handler.write("null");
        }
        if (!(handler.getObject() instanceof Map)) {
            throw new AppJsonException("MapAdapter write error.");
        }
        handler.write("{");
        Map<Object, Object> map = (Map) handler.getObject();
        boolean isMapEmpty = true;
        for (Object key : map.keySet()) {
            if (!isMapEmpty) {//map不空则拼一个','
                handler.write(",");
            }
            handler.write("\"");
            handler.write(key.toString());
            handler.write("\"");
            handler.write(":");
            handler.doWrite(map.get(key));
            isMapEmpty = false;
        }
        handler.write("}");
    }

}
